package seatiger.tomcat.coyote;

import seatiger.tomcat.util.buf.ByteChunk;
import seatiger.tomcat.util.buf.MessageBytes;
import seatiger.tomcat.util.http.MimeHeaders;

import java.io.IOException;
import java.util.Optional;

/**
 * 底层Request对象的封装，封装的都是字节数据
 * 给servlet用户提供的是一个高层的类，用户使用的时候
 * 才会将字节数组转换为数据
 */
public final class Request {
    //请求方法
    private MessageBytes methodMB = MessageBytes.newInstance();
    //带参数的uri
    private MessageBytes unparsedURIMB = MessageBytes.newInstance();
    //uri
    private MessageBytes uriMB = MessageBytes.newInstance();
    //解码后的uri
    private MessageBytes decodedUriMB = MessageBytes.newInstance();
    //请求参数
    private MessageBytes queryMB = MessageBytes.newInstance();
    //协议
    private MessageBytes protoMB = MessageBytes.newInstance();
    //报文头
    private MimeHeaders headers = new MimeHeaders();

    public MimeHeaders getMimeHeaders() {
        return headers;
    }

    public MessageBytes method() {
        return methodMB;
    }

    public MessageBytes unparsedURI() {
        return unparsedURIMB;
    }

    public MessageBytes requestURI() {
        return uriMB;
    }

    public MessageBytes decodedURI() {
        return decodedUriMB;
    }

    public MessageBytes query() {
        return queryMB;
    }

    public MessageBytes queryString() {
        return queryMB;
    }

    public MessageBytes protocol() {
        return protoMB;
    }


    private InputBuffer inputBuffer;

    /**
     * 报文头长度
     */
    private int contentLength = -1;

    public void setInputBuffer(InputBuffer inputBuffer) {
        this.inputBuffer = inputBuffer;
    }

    /**
     * 从数据缓冲区中读取数据，并存入字节块中
     * @param chunk
     * @return
     */
    public int doRead(ByteChunk chunk) throws IOException {
        return inputBuffer.doRead(chunk,this);
    }

    public int getContentLength() {
        if (contentLength > -1) {
            return contentLength;
        }
        contentLength = Optional.ofNullable(headers.getHeader("content-length"))
                .map(value -> Integer.valueOf(value))
                .orElse(-1);
        return contentLength;
    }


    public void recycle() {
        headers.recycle();
        unparsedURIMB.recycle();
        uriMB.recycle();
        decodedUriMB.recycle();
        queryMB.recycle();
        methodMB.recycle();
        protoMB.recycle();
    }
}
